<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Basic Operations on Images</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d5/d10/tutorial_js_root.html">OpenCV.js Tutorials</a></li><li class="navelem"><a class="el" href="../../d1/d78/tutorial_js_table_of_contents_core.html">Core Operations</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Basic Operations on Images </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goal </h2>
<ul>
<li>Learn how to access image properties</li>
<li>Learn how to construct Mat</li>
<li>Learn how to copy Mat</li>
<li>Learn how to convert the type of Mat</li>
<li>Learn how to use MatVector</li>
<li>Learn how to access pixel values and modify them</li>
<li>Learn how to set Region of Interest (ROI)</li>
<li>Learn how to split and merge images</li>
</ul>
<h2>Accessing Image Properties </h2>
<p>Image properties include number of rows, columns and size, depth, channels, type of image data.</p>
<div class="fragment"><div class="line">let src = cv.imread(&quot;canvasInput&quot;);</div><div class="line">console.log(&#39;image width: &#39; + src.cols + &#39;\n&#39; +</div><div class="line">            &#39;image height: &#39; + src.rows + &#39;\n&#39; +</div><div class="line">            &#39;image size: &#39; + src.size().width + &#39;*&#39; + src.size().height + &#39;\n&#39; +</div><div class="line">            &#39;image depth: &#39; + src.depth() + &#39;\n&#39; +</div><div class="line">            &#39;image channels &#39; + src.channels() + &#39;\n&#39; +</div><div class="line">            &#39;image type: &#39; + src.type() + &#39;\n&#39;);</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>src.type() is very important while debugging because a large number of errors in OpenCV.js code are caused by invalid data type.</dd></dl>
<h2>How to construct Mat </h2>
<p>There are 4 basic constructors:</p>
<div class="fragment"><div class="line">// 1. default constructor</div><div class="line">let mat = new cv.Mat();</div><div class="line">// 2. two-dimensional arrays by size and type</div><div class="line">let mat = new cv.Mat(size, type);</div><div class="line">// 3. two-dimensional arrays by rows, cols, and type</div><div class="line">let mat = new cv.Mat(rows, cols, type);</div><div class="line">// 4. two-dimensional arrays by rows, cols, and type with initialization value</div><div class="line">let mat = new cv.Mat(rows, cols, type, new cv.Scalar());</div></div><!-- fragment --><p>There are 3 static functions:</p>
<div class="fragment"><div class="line">// 1. Create a Mat which is full of zeros</div><div class="line">let mat = cv.Mat.zeros(rows, cols, type);</div><div class="line">// 2. Create a Mat which is full of ones</div><div class="line">let mat = cv.Mat.ones(rows, cols, type);</div><div class="line">// 3. Create a Mat which is an identity matrix</div><div class="line">let mat = cv.Mat.eye(rows, cols, type);</div></div><!-- fragment --><p>There are 2 factory functions: </p><div class="fragment"><div class="line">// 1. Use JS array to construct a mat.</div><div class="line">// For example: let mat = cv.matFromArray(2, 2, cv.CV_8UC1, [1, 2, 3, 4]);</div><div class="line">let mat = cv.matFromArray(rows, cols, type, array);</div><div class="line">// 2. Use imgData to construct a mat</div><div class="line">let ctx = canvas.getContext(&quot;2d&quot;);</div><div class="line">let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);</div><div class="line">let mat = cv.matFromImageData(imgData);</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Don't forget to delete <a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv.Mat</a> when you don't want to use it any more.</dd></dl>
<h2>How to copy Mat </h2>
<p>There are 2 ways to copy a Mat:</p>
<div class="fragment"><div class="line">// 1. Clone</div><div class="line">let dst = src.clone();</div><div class="line">// 2. CopyTo(only entries indicated in the mask are copied)</div><div class="line">src.copyTo(dst, mask);</div></div><!-- fragment --><h2>How to convert the type of Mat </h2>
<p>We use the function: <b>convertTo(m, rtype, alpha = 1, beta = 0)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">m</td><td>output matrix; if it does not have a proper size or type before the operation, it is reallocated. </td></tr>
    <tr><td class="paramname">rtype</td><td>desired output matrix type or, rather, the depth since the number of channels are the same as the input has; if rtype is negative, the output matrix will have the same type as the input. </td></tr>
    <tr><td class="paramname">alpha</td><td>optional scale factor. </td></tr>
    <tr><td class="paramname">beta</td><td>optional delta added to the scaled values.</td></tr>
  </table>
  </dd>
</dl>
<div class="fragment"><div class="line">src.convertTo(dst, rtype);</div></div><!-- fragment --><h2>How use MatVector </h2>
<div class="fragment"><div class="line">let mat = new cv.Mat();</div><div class="line">// Initialise a MatVector</div><div class="line">let matVec = new cv.MatVector();</div><div class="line">// Push a Mat back into MatVector</div><div class="line">matVec.push_back(mat);</div><div class="line">// Get a Mat fom MatVector</div><div class="line">let cnt = matVec.get(0);</div><div class="line">mat.delete(); matVec.delete(); cnt.delete();</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Don't forget to delete <a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv.Mat</a>, cv.MatVector and cnt(the Mat you get from MatVector) when you don't want to use them any more.</dd></dl>
<h2>Accessing and Modifying pixel values </h2>
<p>Firstly, you should know the following type relationship:</p>
<table class="doxtable">
<tr>
<th>Data Properties </th><th>C++ Type </th><th>JavaScript Typed Array </th><th>Mat Type  </th></tr>
<tr>
<td>data </td><td>uchar </td><td>Uint8Array </td><td>CV_8U </td></tr>
<tr>
<td>data8S </td><td>char </td><td>Int8Array </td><td>CV_8S </td></tr>
<tr>
<td>data16U </td><td>ushort </td><td>Uint16Array </td><td>CV_16U </td></tr>
<tr>
<td>data16S </td><td>short </td><td>Int16Array </td><td>CV_16S </td></tr>
<tr>
<td>data32S </td><td>int </td><td>Int32Array </td><td>CV_32S </td></tr>
<tr>
<td>data32F </td><td>float </td><td>Float32Array </td><td>CV_32F </td></tr>
<tr>
<td>data64F </td><td>double </td><td>Float64Array </td><td>CV_64F </td></tr>
</table>
<p><b>1. data</b></p>
<div class="fragment"><div class="line">let row = 3, col = 4;</div><div class="line">let src = cv.imread(&quot;canvasInput&quot;);</div><div class="line">if (src.isContinuous()) {</div><div class="line">    let R = src.data[row * src.cols * src.channels() + col * src.channels()];</div><div class="line">    let G = src.data[row * src.cols * src.channels() + col * src.channels() + 1];</div><div class="line">    let B = src.data[row * src.cols * src.channels() + col * src.channels() + 2];</div><div class="line">    let A = src.data[row * src.cols * src.channels() + col * src.channels() + 3];</div><div class="line">}</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Data manipulation is only valid for continuous Mat. You should use isContinuous() to check first.</dd></dl>
<p><b>2. at</b></p>
<table class="doxtable">
<tr>
<th>Mat Type </th><th>At Manipulation  </th></tr>
<tr>
<td>CV_8U </td><td>ucharAt </td></tr>
<tr>
<td>CV_8S </td><td>charAt </td></tr>
<tr>
<td>CV_16U </td><td>ushortAt </td></tr>
<tr>
<td>CV_16S </td><td>shortAt </td></tr>
<tr>
<td>CV_32S </td><td>intAt </td></tr>
<tr>
<td>CV_32F </td><td>floatAt </td></tr>
<tr>
<td>CV_64F </td><td>doubleAt </td></tr>
</table>
<div class="fragment"><div class="line">let row = 3, col = 4;</div><div class="line">let src = cv.imread(&quot;canvasInput&quot;);</div><div class="line">let R = src.ucharAt(row, col * src.channels());</div><div class="line">let G = src.ucharAt(row, col * src.channels() + 1);</div><div class="line">let B = src.ucharAt(row, col * src.channels() + 2);</div><div class="line">let A = src.ucharAt(row, col * src.channels() + 3);</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>At manipulation is only for single channel access and the value can't be modified.</dd></dl>
<p><b>3. ptr</b></p>
<table class="doxtable">
<tr>
<th>Mat Type </th><th>Ptr Manipulation </th><th>JavaScript Typed Array  </th></tr>
<tr>
<td>CV_8U </td><td>ucharPtr </td><td>Uint8Array </td></tr>
<tr>
<td>CV_8S </td><td>charPtr </td><td>Int8Array </td></tr>
<tr>
<td>CV_16U </td><td>ushortPtr </td><td>Uint16Array </td></tr>
<tr>
<td>CV_16S </td><td>shortPtr </td><td>Int16Array </td></tr>
<tr>
<td>CV_32S </td><td>intPtr </td><td>Int32Array </td></tr>
<tr>
<td>CV_32F </td><td>floatPtr </td><td>Float32Array </td></tr>
<tr>
<td>CV_64F </td><td>doublePtr </td><td>Float64Array </td></tr>
</table>
<div class="fragment"><div class="line">let row = 3, col = 4;</div><div class="line">let src = cv.imread(&quot;canvasInput&quot;);</div><div class="line">let pixel = src.ucharPtr(row, col);</div><div class="line">let R = pixel[0];</div><div class="line">let G = pixel[1];</div><div class="line">let B = pixel[2];</div><div class="line">let A = pixel[3];</div></div><!-- fragment --><p>mat.ucharPtr(k) get the k th row of the mat. mat.ucharPtr(i, j) get the i th row and the j th column of the mat.</p>
<h2>Image ROI </h2>
<p>Sometimes, you will have to play with certain region of images. For eye detection in images, first face detection is done all over the image and when face is obtained, we select the face region alone and search for eyes inside it instead of searching whole image. It improves accuracy (because eyes are always on faces) and performance (because we search for a small area)</p>
<p>We use the function: <b>roi (rect)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">rect</td><td>rectangle Region of Interest.</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_basic_ops_roi.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h2>Splitting and Merging Image Channels </h2>
<p>Sometimes you will need to work separately on R,G,B channels of image. Then you need to split the RGB images to single planes. Or another time, you may need to join these individual channels to RGB image.</p>
<div class="fragment"><div class="line">let src = cv.imread(&quot;canvasInput&quot;);</div><div class="line">let rgbaPlanes = new cv.MatVector();</div><div class="line">// Split the Mat</div><div class="line">cv.split(src, rgbaPlanes);</div><div class="line">// Get R channel</div><div class="line">let R = rgbaPlanes.get(0);</div><div class="line">// Merge all channels</div><div class="line">cv.merge(rgbaPlanes, src);</div><div class="line">src.delete(); rgbaPlanes.delete(); R.delete();</div></div><!-- fragment --><dl class="section note"><dt>Note</dt><dd>Don't forget to delete <a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv.Mat</a>, cv.MatVector and R(the Mat you get from MatVector) when you don't want to use them any more.</dd></dl>
<h2>Making Borders for Images (Padding) </h2>
<p>If you want to create a border around the image, something like a photo frame, you can use <b><a class="el" href="../../d2/de8/group__core__array.html#ga2ac1049c2c3dd25c2b41bffe17658a36" title="Forms a border around an image. ">cv.copyMakeBorder()</a></b> function. But it has more applications for convolution operation, zero padding etc. This function takes following arguments:</p>
<ul>
<li><b>src</b> - input image</li>
<li><b>top</b>, <b>bottom</b>, <b>left</b>, <b>right</b> - border width in number of pixels in corresponding directions</li>
<li><b>borderType</b> - Flag defining what kind of border to be added. It can be following types:<ul>
<li><b><a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a></b> - Adds a constant colored border. The value should be given as next argument.<ul>
<li><b><a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5a815c8a89b7cb206dcba14d11b7560f4b" title="fedcba|abcdefgh|hgfedcb ">cv.BORDER_REFLECT</a></b> - Border will be mirror reflection of the border elements, like this : <em>fedcba|abcdefgh|hgfedcb</em></li>
<li><b><a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5ab3c5a6143d8120b95005fa7105a10bb4" title="gfedcb|abcdefgh|gfedcba ">cv.BORDER_REFLECT_101</a></b> or <b><a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5afe14c13a4ea8b8e3b3ef399013dbae01" title="same as BORDER_REFLECT_101 ">cv.BORDER_DEFAULT</a></b> - Same as above, but with a slight change, like this : <em>gfedcb|abcdefgh|gfedcba</em></li>
<li><b><a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aa1de4cff95e3377d6d0cbe7569bd4e9f" title="aaaaaa|abcdefgh|hhhhhhh ">cv.BORDER_REPLICATE</a></b> - Last element is replicated throughout, like this: <em>aaaaaa|abcdefgh|hhhhhhh</em></li>
<li><b><a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5a697c1b011884a7c2bdc0e5caf7955661" title="cdefgh|abcdefgh|abcdefg ">cv.BORDER_WRAP</a></b> - Can't explain, it will look like this : <em>cdefgh|abcdefgh|abcdefg</em></li>
</ul>
</li>
</ul>
</li>
<li><b>value</b> - Color of border if border type is <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a></li>
</ul>
<h2>Try it </h2>
<p> 
<iframe src="../../js_basic_ops_copymakeborder.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
 </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
